/*
 * @Register.java	2008/07/28
 *
 * Copyright 2008 Web & Zen Multimedia, All rights reserved.
 * Use is subject to license terms.
 */
package it.wzm.lightweightlog;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Properties;

/**
 * Where all our Dumper are stored, all extending classes are asked to implement few methods.
 * The register also have a cleanup method, dumper with status 'failure' are removed if they are declared
 * with killonfailure=true.
 */
abstract class Register<T extends Dumper> {
    
    /**
     * The status of this Register
     */
    public enum Status {
        INIT,
        RUNNING,
        SHUTDOWN,
        FAILURE,
    }
	/**
	 * Logger...
	 */
    protected Log logger;
    /**
     * Hold the status of this Register
     */
    private Status status;
    /**
     * Custom set of properties for register...
     */
    private Properties p;
    
    /**
     * Constructor
     * @param p Custom set of properties
     * @param t Array of dumper
     */
    public Register(Properties p, ArrayList<T> t) {
        // initialize our log first then init...
    	logger = LogFactory.getLog();
    	this.init(p,t);
        
    }
    
    /**
     * Overridding class can implement its own action here
     */
    void preinit() {
    }
    
    /**
     * Initialization block
     * @param p set of Properties
     * @param t Array of Dumper
     */
    private void init(Properties p, ArrayList<T> t) {
        // simple assert...
        assert(p!=null && t!=null ): "Error in parameter";
        
        // reference property
        this.p = p;
        
        //init status...
        status=Status.INIT;
        // calling preinit...
        this.preinit();
        
        // browse our dumper array
        // and store in register
        dumper:
            for (T x: t) {
                // check if our dumper is null
                if (x == null) {
                    //LogFactory.getLog().serviceLog("Cannot add null");
                	logger.error("Cannot add null");
                    continue dumper;
                }
                // and then...
                if (!this.save(x)) {
                    //LogFactory.getLog().serviceLog("Couldn't save " + t.toString());
                	logger.error("Couldn't save " + t);
                }
            }
            
            // calling if needed...
            this.postinit();
            status=Status.RUNNING;
    }
    
    /**
     * Get property from our property set...
     * @param name the key to look for
     * @return value of key (null if not present)
     */
    protected String get(String name) {
        for (Object key: p.keySet()) {
            if (((String)key).indexOf(Constant.PROP_ROOT + "register." + name) > -1) {
                return ((String) p.get(key)).trim();
            }
        }
        // nothing found...
        return null;
    }
    
    /**
     * Overridding class can implement its own action here
     */
    void postinit() {
    }
    
    /**
     * Size of this register
     * @return int
     */
    abstract int size();
    
    /**
     * Save dumper to slot
     * @param t extended Dumper
     * @return true if this Dumper is properly saved
     */
    abstract boolean save(T t);
    
    /**
     * Remove dumper from slot
     * @param t extended Dumper
     * @return true if this Dumper is properly saved
     */
    abstract boolean remove(T t);
    
    /**
     * Dispatch a list of entry to each dumper in this register
     * @param ll A LinkedList of Entry
     */
    abstract <E extends Entry> void dispatchToDumper(LinkedList<E> ll);
    
    /**
     * Dispatch an entry to each dumper in this register
     * @param e Any extended Entry
     */
    abstract <E extends Entry> void dispatchToDumper(E e);
    
    /**
     * Close and clean this register
     */
    abstract void shutdown();
    
    /**
     * Overriding the inherited method from Object
     * @return String represenatation for this object
     */
    @Override
    public String toString() {
        
        StringBuffer sb = new StringBuffer();
        
        for (Object key: p.keySet()) {
            if (((String)key).indexOf(Constant.PROP_ROOT + "register.") > -1) {
                sb.append( "," +  ((String)key).replaceAll(Constant.PROP_ROOT + "register.", "") + "=" +  p.get(key) );
            }
        }
        //  returning...
        return super.toString() + " {hc=" + this.hashCode() + "," + this.status + sb + "}" ;
    }
    
}